package com.ztf.serviceThread;

import com.ztf.bean.DataTransfer;
import com.ztf.bean.Message;
import com.ztf.bean.User;
import com.ztf.dao.MsgDao;
import com.ztf.service.Service;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.*;

public class ForwardThread extends Thread{
    private final ObjectInputStream ois;
    private User nowUser;
    private List<Message> waitMessage = new ArrayList<>();

    public ForwardThread(ObjectInputStream ois) {
        this.ois = ois;
    }

    @Override
    public void run(){
        try {
            while (true){
                DataTransfer o = (DataTransfer) ois.readObject();
                switch (o.getType()){
                    case "login":
                        nowUser = (User) o.getObject();
                        if (nowUser.getIdentity().equals("客户")){

                                //客服序号
                                Service.index++;

                                if (Service.index>=Service.serverList.size()){
                                    Service.index=0;
                                }

                                //等待绑定的客服
                                ForwardThread forwardThread = Service.serverList.get(Service.index);

                                Collection<ForwardThread> values = Service.map2.values();
                                Iterator<ForwardThread> iterator = values.iterator();
                                int count = 0;
                                while (iterator.hasNext()){
                                    if (iterator.next()==forwardThread){
                                        count++;
                                    }
                                }
                                if (count>=forwardThread.nowUser.getMaxServerPerson()){
                                    //已达到最大接纳人数  将客户加入等待队列
                                    Service.waitUsers.offer(this);
                                    for (ForwardThread thread : Service.serverList) {
                                        Service.map1.get(thread).writeObject(new DataTransfer("waitUsers",Service.waitUsers.size()));
                                    }
                                    break;
                                }

                            //将客户与客服进行绑定
                            Service.map2.put(this,Service.serverList.get(Service.index));

                            //获取对应绑定的客服的接受线程
                            ForwardThread fort = Service.map2.get(this);
                            ObjectOutputStream oos2 = Service.map1.get(this);
                            ObjectOutputStream oos = Service.map1.get(fort);

                            //将客户分配给对应得客服  客服接待客户首先接受到一个List集合 第一个是这个接待客户的聊天记录,二是这个客户
                            List<Object> objects = new ArrayList<>();
                            objects.add(waitMessage);
                            objects.add(new User(this.nowUser.getName(),this.nowUser.getHead(),this.nowUser.getIdentity()));
                            oos.writeObject(new DataTransfer("client",objects));

                            oos2.writeObject(new DataTransfer("for_you_server",new User(fort.nowUser.getName(),fort.nowUser.getHead(),fort.nowUser.getIdentity())));

                        }else {
                            //客服登录 将客服加入循环链
                            Service.serverList.add(this);
                            if (Service.waitUsers.size()>0){
                                Service.map1.get(this).writeObject(new DataTransfer("waitUsers",Service.waitUsers.size()));
                            }
                            //有新客服登录,则检查等待队列是否有客户,如果有,则进行匹配
                            updateMaxPerson();

                        }
                        break;
                    case "msg":
                        Message message = (Message) o.getObject();
                        User to = message.getTo();
                        if (to==null){
                            //说明客户在等待,只需要发给自己就好了
                            ObjectOutputStream oos2 = Service.map1.get(this);
                            oos2.writeObject(new DataTransfer("msg",message));
                            waitMessage.add(message);
                            break;
                        }
                        Set<ForwardThread> ft = Service.map1.keySet();
                        for (ForwardThread f : ft) {
                            //得到接受人的转发线程
                            if (f.nowUser.equals(to)){
                                ObjectOutputStream oos = Service.map1.get(f);
                                oos.writeObject(new DataTransfer("msg",message));
                                Service.map1.get(this).writeObject(new DataTransfer("msg",message));
                                break;

                            }
                        }
                        break;
                    case "updateMaxPerson":
                        int max = (int) o.getObject();
                        nowUser.setMaxServerPerson(max);
                        updateMaxPerson();
                        break;
                    case "inputing":
                        User isChating = (User) o.getObject();
                        Set<ForwardThread> keySet = Service.map1.keySet();
                        for (ForwardThread thread : keySet) {
                            if (thread.nowUser.equals(isChating)){
                                Service.map1.get(thread).writeObject(new DataTransfer("i_am_talking",""));
                                break;
                            }
                        }
                        break;
                    case "saveMessage":
                        List<Object> object = (List<Object>) o.getObject();

                        String name = (String) object.get(0);
                        List<Message> list = (List<Message>) object.get(1);
                        Long aLong = (Long) object.get(2);

                        MsgDao.saveService(nowUser.getName(),name,aLong);
                        MsgDao.addMsg(list);
                        break;


                }
            }
        }catch (Exception e){
            if (nowUser.getIdentity().equals("客户")){

                //从等待队列中移除当前退出客户
                boolean remove = Service.waitUsers.remove(this);
                if (remove){
                    updateWaitUsers();
                }

                //获取当前退出客户所对应的客服,获取客服的接受线程
                ForwardThread forwardThread1 = Service.map2.get(this);
                if (forwardThread1!=null){
                    //说明是有进行配对的客户退出
                    //获取对应客服的输出流  ****
                    ObjectOutputStream objectOutputStream = Service.map1.get(forwardThread1);
                    try {
                        objectOutputStream.writeObject(new DataTransfer("offline",new User(nowUser.getName(),nowUser.getHead(),nowUser.getIdentity())));
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                    Service.map2.remove(this);
                }


                Service.map1.remove(this);


                //有客户离开时,则可以将等待队列中的客户与空闲客服配对
                updateMaxPerson();


            }else {
                //客服下线
                System.out.println("客服下线");
                Service.map1.remove(this);
                Service.serverList.remove(this);
            }
            System.err.println("断开链接");
        }
    }

    public void updateMaxPerson(){

        if (Service.waitUsers.size()!=0){
            //从队列中弹出客户
            ForwardThread poll = Service.waitUsers.poll();

            while (true){
                //客服序号
                Service.index++;

                if (Service.index>=Service.serverList.size()){
                    Service.index=0;
                }

                //等待绑定的客服
                ForwardThread forwardThread = Service.serverList.get(Service.index);
                int count = 0;

                //获取已经在服务的客服集合
                Collection<ForwardThread> values = Service.map2.values();

                try {
                    sleep(50);
                    for (ForwardThread value : values) {
                        if (value==forwardThread){
                            count++;
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }


                if (count<forwardThread.nowUser.getMaxServerPerson()){
                    //未达到最大接纳人数  进行客户与客服的配对
                    Service.map2.put(poll,forwardThread);


                    ObjectOutputStream oos = Service.map1.get(forwardThread);
                    ObjectOutputStream oos2 = Service.map1.get(poll);

                    //将客户分配给对应得客服
                    try {

                        List<Object> objects = new ArrayList<>();
                        objects.add(poll.waitMessage);
                        objects.add(new User(poll.nowUser.getName(),poll.nowUser.getHead(),poll.nowUser.getIdentity()));
                        oos.writeObject(new DataTransfer("client",objects));


                        oos2.writeObject(new DataTransfer("for_you_server",new User(forwardThread.nowUser.getName(),forwardThread.nowUser.getHead(),forwardThread.nowUser.getIdentity(),forwardThread.nowUser.getMaxServerPerson())));

                        updateWaitUsers();
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                    //统计当前登录客服能够接纳最大得客户总数
                    int count2 = 0;
                    for (ForwardThread thread : Service.serverList) {
                        count2+=thread.nowUser.getMaxServerPerson();
                    }
                    //如果当前等待队伍还有客户且 最大接纳总数之和大于已经在接待得客户数目则再进行一次客服与客户的配对
                    if (Service.waitUsers.size()!=0 && Service.map2.size()<count2){
                        updateMaxPerson();
                    }
                    break;
                }

            }
        }
    }

    //更新客服面板显示的等待人数
    public void updateWaitUsers(){
        try {
            for (ForwardThread thread : Service.serverList) {
                Service.map1.get(thread).writeObject(new DataTransfer("waitUsers",Service.waitUsers.size()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}
